"""Object that monitors phone states."""

import re

class PhoneMonitor(object):

    _xLockRe = re.compile(r"\.X(\d+)-lock")
    _name = r"\w[^:]+" # just helper
    _value = r"\S+"  # and another helper
    _xSettingHeader = re.compile(r"^(?P<name>%s):$" % _name)
    _xSettingValue = re.compile(
        r"\s*(?P<name>%s):\s*(?P<value>%s)" % (_name, _value))

    # script for temporary screensaver disable
    _screenOffScr = """\
        xset -display :%(display)s s off ; \
        kill -0 $PPID ;\
        while [ "$?" == "0" ] ; do \
            sleep 10; \
            kill -0 $PPID; \
        done; \
        xset -display :%(display)s s %(timeout)s; \
    """

    # externally accessible fields follow
    xDisplays = ()
    xSettings = None

    def __init__(self, app):
        self._app = app

    def fetchData(self):
        """Update this object from remote data."""
        self._fetchXDisplays()
        self._fetchXSettings()

    def _fetchXDisplays(self):
        """Fetch list of active X displays."""
        _p = self._app.executeRemote("ls -1 /tmp/.X*-lock")
        _p.wait()
        _found = _p.stdout.read().strip()
        _displays = []
        _match = self._xLockRe.search(_found)
        while _match:
            _displays.append(_match.group(1))
            _found = _found[_match.end():]
            _match = self._xLockRe.search(_found)
        if _displays:
            self._app.log_debug("Found X displays: %r" % _displays)
        else:
            self._app.log_debug("Failed to find any X displays")
        self.xDisplays = tuple(_displays)

    def _fetchXSettings(self):
        """Fetch settings for all found X displays."""
        _allSettings = {}
        for _disp in self.xDisplays:
            _p = self._app.executeRemote(
                "xset -display :%s q" % _disp)
            _p.wait()
            _data = _p.stdout.read().strip()
            # first things first -- fetch sections and their raw data
            _sectionName = None
            _raw = []
            _settings = {}
            for _line in _data.splitlines():
                # last \n is stripped bu `splitlines`
                _match = self._xSettingHeader.match(_line)
                if _match:
                    if _sectionName:
                        _settings[_sectionName] = {
                            "raw": "\n".join(_raw)
                        }
                    _sectionName = _match.group("name")
                    _raw = []
                else:
                    _raw.append(_line)
            if _sectionName:
                _settings[_sectionName] = {
                    "raw": "\n".join(_raw)
                }
            # now to parse raw data
            for _val in _settings.itervalues():
                _val.update(self._parseXSettingValues(_val["raw"]))
            _allSettings[_disp] = _settings
        self.xSettings = _allSettings

    def _parseXSettingValues(self, line):
        """Parse X settings in given string."""
        _rv = {}
        _match = self._xSettingValue.search(line)
        while _match:
            _rv[_match.group("name")] = _match.group("value")
            line = line[:_match.start()] + line[_match.end():]
            _match = self._xSettingValue.search(line)
        return _rv

    def tmpDisableXScreensaver(self, display):
        """Temporary disable X screensaver on given display.

        (Restore old settings on session termination).

        P.S. : this disable suspend on Neo1973/GTA02.

        """
        _p = self._app.executeRemote(self._screenOffScr % {
            "display": display,
            "timeout": self.xSettings[str(display)]["Screen Saver"]["timeout"],
        })

# vim: set sts=4 sw=4 et :
